use actix_http::StatusCode;
use actix_session::Session;
use actix_web::{
    web::{self, ServiceConfig},
    HttpResponse,
};

use crate::{
    errors::cons_error,
    middlewares::authorize::{club_getters::default_getter, Authorize},
    models::user::{NormalUserModel, UserModelDTO, UserRole},
    services::user_service::{AccountPassowrdLoginReq, UserService},
    AppError, AppResult,
};
use actix_web::http::Method;

mod ctrl_struct {
    use serde::{Deserialize, Serialize};
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct UpdatePasswordCtrlReq {
        pub password: String,
    }
}

async fn account_password_login(
    user_service: web::Data<UserService>,
    session: Session,
    req: web::Json<AccountPassowrdLoginReq>,
) -> AppResult<HttpResponse> {
    let req = req.into_inner();
    let user = user_service.account_password_login(&req, None).await?;
    UserService::set_user_to_session(&session, &user)?;
    Ok(HttpResponse::Ok().json(UserModelDTO::from(user)))
}
/// ## get_user_info
/// 获取用户信息
/// `/api/authorize/self` `[get]`
async fn get_user_info(session: Session) -> AppResult<HttpResponse> {
    let user = UserService::get_user_from_session(&session)?;
    Ok(HttpResponse::Ok().json(UserModelDTO::from(user)))
}

/// ## logout
/// 用户注销
/// `/api/authorize/self` `[delete]`
async fn logout(session: Session) -> AppResult<HttpResponse> {
    UserService::remove_user_from_session(&session)?;
    Ok(HttpResponse::NoContent().finish())
}

/// ## update_password
/// 更新用户密码
/// `/api/authorize/self/ap` `[put]`
async fn update_password(
    user_service: web::Data<UserService>,
    user: NormalUserModel,
    req: web::Json<ctrl_struct::UpdatePasswordCtrlReq>,
) -> AppResult<HttpResponse> {
    let account = user_service.get_user_account(user.id).await?;
    log::info!("account :{:?}", account);
    let password = req.into_inner().password;
    user_service
        .update_password(
            account.id.ok_or_else(|| {
                AppError::Status(
                    StatusCode::INTERNAL_SERVER_ERROR,
                    cons_error::MSG_MDB.into(),
                )
            })?,
            password,
        )
        .await?;
    Ok(HttpResponse::NoContent().finish())
}
pub fn configure_authorize_controller(config: &mut ServiceConfig) {
    config
        .service(
            web::resource("/self")
                .wrap(Authorize::new(UserRole::Guest, default_getter).method(Method::GET))
                .route(web::delete().to(logout))
                .route(web::get().to(get_user_info)),
        )
        .service(
            web::resource("/self/ap")
                .route(web::post().to(account_password_login))
                .route(web::put().to(update_password)),
        );
}
